#include "Epoll.h"
#include <errno.h>
#include "log4z.h"

/** epoll_create **/
Epoll::Epoll(int flags, int noFile) : fdNumber(0), nReady(0)
{

#if defined(_WIN32)
	m_epollfd = ::epoll_create(1024);
	if (m_epollfd == nullptr) {
#else
	m_epollfd = ::epoll_create1(flags);
	if (m_epollfd == -1) {
#endif
		LOGFMTE(" epoll_create1 failed:%s", strerror(errno));
	}
}
Epoll::~Epoll()
{
	this->close();
}

/** epoll_ctl **/
int Epoll::addfd(int fd, uint32_t events, bool ETorNot)
{
#if defined(_WIN32)
	if (m_epollfd == nullptr) {
#else
	if (m_epollfd == -1) {
#endif
		LOGFMTE(" m_epollfd is vaild");
		return -1;
	}
	memset(&event, 0, sizeof(event));
	event.events = events;
	if (ETorNot)
		event.events |= EPOLLET;
	event.data.fd = fd;
	if (::epoll_ctl(m_epollfd, EPOLL_CTL_ADD, fd, &event) == -1) {
		LOGFMTE(" epoll add fd failed:%s", strerror(errno));
		return -1;
	}
	++fdNumber;
	return 0;
}
void Epoll::modfd(int fd, uint32_t events, bool ETorNot)
{
#if defined(_WIN32)
	if (m_epollfd == nullptr) {
#else
	if (m_epollfd == -1) {
#endif
		LOGFMTE(" m_epollfd is vaild");
		return;
	}
	memset(&event, 0, sizeof(event));
	event.events = events;
	if (ETorNot)
		event.events |= EPOLLET;
	event.data.fd = fd;
	if (::epoll_ctl(m_epollfd, EPOLL_CTL_MOD, fd, &event) == -1) {
		LOGFMTE(" epoll mod fd failed:%s", strerror(errno));
		return;
	}
}
void Epoll::delfd(int fd)
{
#if defined(_WIN32)
	if (m_epollfd == nullptr) {
#else
	if (m_epollfd == -1) {
#endif
		LOGFMTE("m_epollfd is vaild");
		return;
	}
	memset(&event, 0, sizeof(event));
	event.data.fd = fd;
	if (::epoll_ctl(m_epollfd, EPOLL_CTL_DEL, fd, &event) == -1) {
		LOGFMTE(" epoll del fd failed:%s", strerror(errno));
		return;
	}
	--fdNumber;
}

/** epoll_wait **/
int Epoll::wait(int timeout)
{
#if defined(_WIN32)
	if (m_epollfd == nullptr) {
#else
	if (m_epollfd == -1) {
#endif
		LOGFMTE(" wait m_epollfd is vaild");
		return -1;
	}
	events.resize(fdNumber);
	while (true)
	{
		nReady = epoll_wait(m_epollfd, &*events.begin(), fdNumber, timeout);
		if (nReady == 0)
			return 0;
		else if (nReady == -1)
		{
			if (errno == EINTR)
				continue;
			else
				return -1;
		}
		else
			return nReady;
	}
	return -1;
}

int Epoll::getEventOccurfd(int eventIndex) const
{
	if (eventIndex > nReady)
		return -1;
	return events[eventIndex].data.fd;
}

uint32_t Epoll::getEvents(int eventIndex) const
{
	if (eventIndex > nReady)
		return -1;
	return events[eventIndex].events;
}



